home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Plotting / aa_Intel_Only / Gnuplot / GnuplotSource / misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  25.4 KB  |  958 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: misc.c%v 3.38.2.120 1993/04/26 00:25:11 woo Exp woo $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - misc.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted, 
  12.  * provided that the above copyright notice appear in all copies and 
  13.  * that both that copyright notice and this permission notice appear 
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the modified code.  Modifications are to be distributed 
  18.  * as patches to released version.
  19.  *  
  20.  * This software is provided "as is" without express or implied warranty.
  21.  * 
  22.  *
  23.  * AUTHORS
  24.  *
  25.  *   Original Software:
  26.  *     Thomas Williams,  Colin Kelley.
  27.  * 
  28.  *   Gnuplot 2.0 additions:
  29.  *       Russell Lang, Dave Kotz, John Campbell.
  30.  *
  31.  *   Gnuplot 3.0 additions:
  32.  *       Gershon Elber and many others.
  33.  *
  34.  * 19 September 1992  Lawrence Crowl  (crowl@cs.orst.edu)
  35.  * Added user-specified bases for log scaling.
  36.  * 
  37.  * Send your comments or suggestions to 
  38.  *  info-gnuplot@dartmouth.edu.
  39.  * This is a mailing list; to join it send a note to 
  40.  *  info-gnuplot-request@dartmouth.edu.  
  41.  * Send bug reports to
  42.  *  bug-gnuplot@dartmouth.edu.
  43.  */
  44.  
  45. #include <stdio.h>
  46. #include <math.h>
  47. #ifndef __PUREC__
  48. #ifndef VMS
  49. #ifdef AMIGA_AC_5
  50. #include <exec/types.h>
  51. #else
  52. #include <sys/types.h>
  53. #endif /* AMIGA_AC_5 */
  54. #else
  55. #include <types.h>
  56. #endif
  57. #endif /* __PUREC__ */
  58. #include "plot.h"
  59. #include "setshow.h"
  60. #ifndef _Windows
  61. #include "help.h"
  62. #endif
  63.  
  64. #if !defined(__TURBOC__) && !defined (_IBMR2) && !defined (ATARI) && !defined (AMIGA_SC_6_1) && !defined(OSF1)
  65. extern char *malloc();
  66. extern char *realloc();
  67. #endif
  68.  
  69. #if defined(__TURBOC__) && (defined(MSDOS) || defined(_Windows))
  70. #include <alloc.h>        /* for malloc, farmalloc, farrealloc */
  71. #endif
  72. #if defined(sequent)
  73. #include <sys/types.h>          /* typedef long size_t; */
  74. #endif
  75.  
  76. extern int c_token;
  77. extern char replot_line[];
  78. extern struct at_type at;
  79. extern struct ft_entry ft[];
  80. extern struct udft_entry *first_udf;
  81. extern struct udvt_entry *first_udv;
  82.  
  83. extern struct at_type *temp_at();
  84.  
  85. extern TBOOLEAN interactive;
  86. extern char *infile_name;
  87. extern int inline_num;
  88.  
  89. /* State information for load_file(), to recover from errors
  90.  * and properly handle recursive load_file calls
  91.  */
  92. typedef struct lf_state_struct LFS;
  93. struct lf_state_struct {
  94.     FILE *fp;                /* file pointer for load file */
  95.     char *name;            /* name of file */
  96.     TBOOLEAN interactive;        /* value of interactive flag on entry */
  97.     int inline_num;            /* inline_num on entry */
  98.     LFS *prev;                /* defines a stack */
  99. } *lf_head = NULL;            /* NULL if not in load_file */
  100.  
  101. static TBOOLEAN lf_pop();
  102. static void lf_push();
  103. FILE *lf_top();
  104.  
  105.  
  106. /*
  107.  * instead of <strings.h>
  108.  */
  109. #ifdef _Windows
  110. #include <string.h>
  111. #else
  112. #ifndef AMIGA_SC_6_1
  113. extern int strcmp();
  114. #endif /* !AMIGA_SC_6_1 */
  115. #endif
  116.  
  117. /* alloc:
  118.  * allocate memory 
  119.  * This is a protected version of malloc. It causes an int_error 
  120.  * if there is not enough memory, but first it tries FreeHelp() 
  121.  * to make some room, and tries again. If message is NULL, we 
  122.  * allow NULL return. Otherwise, we handle the error, using the
  123.  * message to create the int_error string. Note cp/sp_extend uses realloc,
  124.  * so it depends on this using malloc().
  125.  */
  126.  
  127. char *
  128. alloc(size, message)
  129.     unsigned long size;        /* # of bytes */
  130.     char *message;            /* description of what is being allocated */
  131. {
  132.     char *p;                /* the new allocation */
  133.     char errbuf[100];        /* error message string */
  134.  
  135.     p = malloc((size_t)size);
  136.     if (p == (char *)NULL) {
  137. #ifndef vms
  138. #ifndef _Windows
  139.        FreeHelp();            /* out of memory, try to make some room */
  140. #endif
  141. #endif
  142.        p = malloc((size_t)size);        /* try again */
  143.        if (p == (char *)NULL) {
  144.           /* really out of memory */
  145.           if (message != NULL) {
  146.              (void) sprintf(errbuf, "out of memory for %s", message);
  147.              int_error(errbuf, NO_CARET);
  148.              /* NOTREACHED */
  149.           }
  150.           /* else we return NULL */
  151.        }
  152.     }
  153.     return(p);
  154. }
  155.  
  156. /*
  157.  * cp_alloc() allocates a curve_points structure that can hold 'num'
  158.  * points.
  159.  */
  160. struct curve_points *
  161. cp_alloc(num)
  162.     int num;
  163. {
  164.     struct curve_points *cp;
  165.     cp = (struct curve_points *) alloc((unsigned long)sizeof(struct curve_points), "curve");
  166.     cp->p_max = (num >= 0 ? num : 0);
  167.     if (num > 0) {
  168.        cp->points = (struct coordinate GPHUGE *)
  169.         gpfaralloc((unsigned long)num * sizeof(struct coordinate), "curve points");
  170.     } else
  171.        cp->points = (struct coordinate GPHUGE *) NULL;
  172.     cp->next_cp = NULL;
  173.     cp->title = NULL;
  174.     return(cp);
  175. }
  176.  
  177.  
  178. /*
  179.  * cp_extend() reallocates a curve_points structure to hold "num"
  180.  * points. This will either expand or shrink the storage.
  181.  */
  182. cp_extend(cp, num)
  183.     struct curve_points *cp;
  184.     int num;
  185. {
  186.     struct coordinate GPHUGE *new;
  187.  
  188. #if (defined(MSDOS) || defined(_Windows))  &&  !defined(WIN32)
  189.     /* Make sure we do not allocate more than 64k points in msdos since 
  190.      * indexing is done with 16-bit int
  191.      * Leave some bytes for malloc maintainance.
  192.      */
  193.     if (num > 32700)
  194.         int_error("Array index must be less than 32k in msdos", NO_CARET);
  195. #endif /* MSDOS */
  196.  
  197.     if (num == cp->p_max) return(0);
  198.  
  199.     if (num > 0) {
  200.        if (cp->points == NULL) {
  201.           cp->points = (struct coordinate GPHUGE *)
  202.             gpfaralloc((unsigned long)num * sizeof(struct coordinate), "curve points");
  203.        } else {
  204.           new = (struct coordinate GPHUGE *)
  205.             gpfarrealloc(cp->points, (unsigned long)num * sizeof(struct coordinate));
  206.           if (new == (struct coordinate GPHUGE *) NULL) {
  207.              int_error("No memory available for expanding curve points",
  208.                      NO_CARET);
  209.              /* NOTREACHED */
  210.           }
  211.           cp->points = new;
  212.        }
  213.        cp->p_max = num;
  214.     } else {
  215.        if (cp->points != (struct coordinate GPHUGE *) NULL)
  216.         gpfarfree(cp->points);
  217.        cp->points = (struct coordinate GPHUGE *) NULL;
  218.        cp->p_max = 0;
  219.     }
  220. }
  221.  
  222. /*
  223.  * cp_free() releases any memory which was previously malloc()'d to hold
  224.  *   curve points (and recursively down the linked list).
  225.  */
  226. cp_free(cp)
  227. struct curve_points *cp;
  228. {
  229.     if (cp) {
  230.         cp_free(cp->next_cp);
  231.         if (cp->title)
  232.             free((char *)cp->title);
  233.         if (cp->points)
  234.             gpfarfree((char *)cp->points);
  235.         free((char *)cp);
  236.     }
  237. }
  238.  
  239. /*
  240.  * iso_alloc() allocates a iso_curve structure that can hold 'num'
  241.  * points.
  242.  */
  243. struct iso_curve *
  244. iso_alloc(num)
  245.     int num;
  246. {
  247.     struct iso_curve *ip;
  248.     ip = (struct iso_curve *) alloc((unsigned long)sizeof(struct iso_curve), "iso curve");
  249.     ip->p_max = (num >= 0 ? num : 0);
  250.     if (num > 0) {
  251.        ip->points = (struct coordinate GPHUGE *)
  252.         gpfaralloc((unsigned long)num * sizeof(struct coordinate), "iso curve points");
  253.     } else
  254.        ip->points = (struct coordinate GPHUGE *) NULL;
  255.     ip->next = NULL;
  256.     return(ip);
  257. }
  258.  
  259. /*
  260.  * iso_extend() reallocates a iso_curve structure to hold "num"
  261.  * points. This will either expand or shrink the storage.
  262.  */
  263. iso_extend(ip, num)
  264.     struct iso_curve *ip;
  265.     int num;
  266. {
  267.     struct coordinate GPHUGE *new;
  268.  
  269.     if (num == ip->p_max) return(0);
  270.  
  271. #if (defined(MSDOS) || defined(_Windows))  &&  !defined(WIN32)
  272.     /* Make sure we do not allocate more than 64k points in msdos since 
  273.      * indexing is done with 16-bit int
  274.      * Leave some bytes for malloc maintainance.
  275.      */
  276.     if (num > 32700)
  277.         int_error("Array index must be less than 32k in msdos", NO_CARET);
  278. #endif /* MSDOS */
  279.  
  280.     if (num > 0) {
  281.        if (ip->points == NULL) {
  282.           ip->points = (struct coordinate GPHUGE *)
  283.             gpfaralloc((unsigned long)num * sizeof(struct coordinate), "iso curve points");
  284.        } else {
  285.           new = (struct coordinate GPHUGE *)
  286.             gpfarrealloc(ip->points, (unsigned long)num * sizeof(struct coordinate));
  287.           if (new == (struct coordinate GPHUGE *) NULL) {
  288.              int_error("No memory available for expanding curve points",
  289.                      NO_CARET);
  290.              /* NOTREACHED */
  291.           }
  292.           ip->points = new;
  293.        }
  294.        ip->p_max = num;
  295.     } else {
  296.        if (ip->points != (struct coordinate GPHUGE *) NULL)
  297.         gpfarfree(ip->points);
  298.        ip->points = (struct coordinate GPHUGE *) NULL;
  299.        ip->p_max = 0;
  300.     }
  301. }
  302.  
  303. /*
  304.  * iso_free() releases any memory which was previously malloc()'d to hold
  305.  *   iso curve points.
  306.  */
  307. iso_free(ip)
  308. struct iso_curve *ip;
  309. {
  310.     if (ip) {
  311.         if (ip->points)
  312.             gpfarfree((char *)ip->points);
  313.         free((char *)ip);
  314.     }
  315. }
  316.  
  317. /*
  318.  * sp_alloc() allocates a surface_points structure that can hold 'num_iso_1'
  319.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  320.  * 'num_samp_1' samples.
  321.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  322.  */
  323. struct surface_points *
  324. sp_alloc(num_samp_1,num_iso_1,num_samp_2,num_iso_2)
  325.     int num_samp_1,num_iso_1,num_samp_2,num_iso_2;
  326. {
  327.     struct surface_points *sp;
  328.  
  329.     sp = (struct surface_points *) alloc((unsigned long)sizeof(struct surface_points), "surface");
  330.     sp->next_sp = NULL;
  331.     sp->title = NULL;
  332.     sp->contours = NULL;
  333.     sp->iso_crvs = NULL;
  334.     sp->num_iso_read = 0;
  335.  
  336.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  337.     int i;
  338.     struct iso_curve *icrv;
  339.  
  340.     for (i = 0; i < num_iso_1; i++) {
  341.         icrv = iso_alloc(num_samp_2);
  342.         icrv->next = sp->iso_crvs;
  343.         sp->iso_crvs = icrv;
  344.     }
  345.     for (i = 0; i < num_iso_2; i++) {
  346.         icrv = iso_alloc(num_samp_1);
  347.         icrv->next = sp->iso_crvs;
  348.         sp->iso_crvs = icrv;
  349.     }
  350.     } else
  351.     sp->iso_crvs = (struct iso_curve *) NULL;
  352.  
  353.     return(sp);
  354. }
  355.  
  356. /*
  357.  * sp_replace() updates a surface_points structure so it can hold 'num_iso_1'
  358.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  359.  * 'num_samp_1' samples.
  360.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  361.  */
  362. sp_replace(sp,num_samp_1,num_iso_1,num_samp_2,num_iso_2)
  363.        struct surface_points *sp;
  364.        int num_samp_1,num_iso_1,num_samp_2,num_iso_2;
  365. {
  366.     int i;
  367.     struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  368.  
  369.     while ( icrvs ) {
  370.     icrv = icrvs;
  371.     icrvs = icrvs->next;
  372.     iso_free( icrv );
  373.     }
  374.     sp->iso_crvs = NULL;
  375.     
  376.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  377.     for (i = 0; i < num_iso_1; i++) {
  378.         icrv = iso_alloc(num_samp_2);
  379.         icrv->next = sp->iso_crvs;
  380.         sp->iso_crvs = icrv;
  381.     }
  382.     for (i = 0; i < num_iso_2; i++) {
  383.         icrv = iso_alloc(num_samp_1);
  384.         icrv->next = sp->iso_crvs;
  385.         sp->iso_crvs = icrv;
  386.     }
  387.     } else
  388.     sp->iso_crvs = (struct iso_curve *) NULL;
  389. }
  390.  
  391. /*
  392.  * sp_free() releases any memory which was previously malloc()'d to hold
  393.  *   surface points.
  394.  */
  395. sp_free(sp)
  396. struct surface_points *sp;
  397. {
  398.     if (sp) {
  399.         sp_free(sp->next_sp);
  400.         if (sp->title)
  401.             free((char *)sp->title);
  402.         if (sp->contours) {
  403.             struct gnuplot_contours *cntr, *cntrs = sp->contours;
  404.  
  405.             while (cntrs) {
  406.                 cntr = cntrs;
  407.                 cntrs = cntrs->next;
  408.                 gpfarfree(cntr->coords);
  409.                 free(cntr);
  410.             }
  411.         }
  412.         if (sp->iso_crvs) {
  413.             struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  414.  
  415.             while (icrvs) {
  416.                 icrv = icrvs;
  417.                 icrvs = icrvs->next;
  418.                 iso_free(icrv);
  419.             }
  420.         }
  421.         free((char *)sp);
  422.     }
  423. }
  424.  
  425.  
  426.  
  427. save_functions(fp)
  428. FILE *fp;
  429. {
  430. register struct udft_entry *udf = first_udf;
  431.  
  432.     if (fp) {
  433.         while (udf) {
  434.             if (udf->definition)
  435.                 fprintf(fp,"%s\n",udf->definition);
  436.             udf = udf->next_udf;
  437.         }
  438.         (void) fclose(fp);
  439.     } else
  440.         os_error("Cannot open save file",c_token);            
  441. }
  442.  
  443.  
  444. save_variables(fp)
  445. FILE *fp;
  446. {
  447. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  448.  
  449.     if (fp) {
  450.         while (udv) {
  451.             if (!udv->udv_undef) {
  452.                 fprintf(fp,"%s = ",udv->udv_name);
  453.                 disp_value(fp,&(udv->udv_value));
  454.                 (void) putc('\n',fp);
  455.             }
  456.             udv = udv->next_udv;
  457.         }
  458.         (void) fclose(fp);
  459.     } else
  460.         os_error("Cannot open save file",c_token);            
  461. }
  462.  
  463.  
  464. save_all(fp)
  465. FILE *fp;
  466. {
  467. register struct udft_entry *udf = first_udf;
  468. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  469.  
  470.     if (fp) {
  471.         save_set_all(fp);
  472.         while (udf) {
  473.             if (udf->definition)
  474.                 fprintf(fp,"%s\n",udf->definition);
  475.             udf = udf->next_udf;
  476.         }
  477.         while (udv) {
  478.             if (!udv->udv_undef) {
  479.                 fprintf(fp,"%s = ",udv->udv_name);
  480.                 disp_value(fp,&(udv->udv_value));
  481.                 (void) putc('\n',fp);
  482.             }
  483.             udv = udv->next_udv;
  484.         }
  485.         fprintf(fp,"%s\n",replot_line);
  486.         (void) fclose(fp);
  487.     } else
  488.         os_error("Cannot open save file",c_token);            
  489. }
  490.  
  491.  
  492. save_set(fp)
  493. FILE *fp;
  494. {
  495.     if (fp) {
  496.         save_set_all(fp);
  497.         (void) fclose(fp);
  498.     } else
  499.         os_error("Cannot open save file",c_token);            
  500. }
  501.  
  502.  
  503. save_set_all(fp)
  504. FILE *fp;
  505. {
  506. struct text_label *this_label;
  507. struct arrow_def *this_arrow;
  508. char *quote;
  509.     fprintf(fp,"set terminal %s %s\n", term_tbl[term].name, term_options);
  510.     fprintf(fp,"set output %s\n",strcmp(outstr,"STDOUT")? outstr : "" );
  511.     fprintf(fp,"set %sclip points\n", (clip_points)? "" : "no");
  512.     fprintf(fp,"set %sclip one\n", (clip_lines1)? "" : "no");
  513.     fprintf(fp,"set %sclip two\n", (clip_lines2)? "" : "no");
  514.     fprintf(fp,"set %sborder\n",draw_border ? "" : "no");
  515.     if (boxwidth<0.0)
  516.         fprintf(fp,"set boxwidth\n");
  517.     else
  518.         fprintf(fp,"set boxwidth %g\n",boxwidth);
  519.     fprintf(fp,"set dummy %s,%s\n",dummy_var[0], dummy_var[1]);
  520.     fprintf(fp,"set format x \"%s\"\n", xformat);
  521.     fprintf(fp,"set format y \"%s\"\n", yformat);
  522.     fprintf(fp,"set format z \"%s\"\n", zformat);
  523.     fprintf(fp,"set %sgrid\n", (grid)? "" : "no");
  524.     switch (key) {
  525.         case -1 :
  526.             fprintf(fp,"set key\n");
  527.             break;
  528.         case 0 :
  529.             fprintf(fp,"set nokey\n");
  530.             break;
  531.         case 1 :
  532.             fprintf(fp,"set key %g,%g,%g\n",key_x,key_y,key_z);
  533.             break;
  534.     }
  535.     fprintf(fp,"set nolabel\n");
  536.     for (this_label = first_label; this_label != NULL;
  537.             this_label = this_label->next) {
  538.         fprintf(fp,"set label %d \"%s\" at %g,%g,%g ",
  539.                this_label->tag,
  540.                this_label->text, this_label->x,
  541.                          this_label->y,
  542.                          this_label->z);
  543.         switch(this_label->pos) {
  544.             case LEFT :
  545.                 fprintf(fp,"left");
  546.                 break;
  547.             case CENTRE :
  548.                 fprintf(fp,"centre");
  549.                 break;
  550.             case RIGHT :
  551.                 fprintf(fp,"right");
  552.                 break;
  553.         }
  554.         fputc('\n',fp);
  555.     }
  556.     fprintf(fp,"set noarrow\n");
  557.     for (this_arrow = first_arrow; this_arrow != NULL;
  558.             this_arrow = this_arrow->next) {
  559.         fprintf(fp,"set arrow %d from %g,%g,%g to %g,%g,%g%s\n",
  560.                this_arrow->tag,
  561.                this_arrow->sx, this_arrow->sy, this_arrow->sz,
  562.                this_arrow->ex, this_arrow->ey, this_arrow->ez,
  563.                this_arrow->head ? "" : " nohead");
  564.     }
  565.     fprintf(fp,"set nologscale\n");
  566.     if (is_log_x) fprintf(fp,"set logscale x %g\n", base_log_x);
  567.     if (is_log_y) fprintf(fp,"set logscale y %g\n", base_log_y);
  568.     if (is_log_z) fprintf(fp,"set logscale z %g\n", base_log_z);
  569.     fprintf(fp,"set offsets %g, %g, %g, %g\n",loff,roff,toff,boff);
  570.     fprintf(fp,"set %spolar\n", (polar)? "" : "no");
  571.     fprintf(fp,"set angles %s\n", (angles_format == ANGLES_RADIANS)?
  572.                         "radians" : "degrees");
  573.     fprintf(fp,"set %sparametric\n", (parametric)? "" : "no");
  574.     fprintf(fp,"set view %g, %g, %g, %g\n",
  575.         surface_rot_x, surface_rot_z, surface_scale, surface_zscale);
  576.     fprintf(fp,"set samples %d, %d\n",samples_1,samples_2);
  577.     fprintf(fp,"set isosamples %d, %d\n",iso_samples_1,iso_samples_2);
  578.     fprintf(fp,"set %ssurface\n",(draw_surface) ? "" : "no");
  579.     fprintf(fp,"set %scontour",(draw_contour) ? "" : "no");
  580.     switch (draw_contour) {
  581.         case CONTOUR_NONE: fprintf(fp, "\n"); break;
  582.         case CONTOUR_BASE: fprintf(fp, " base\n"); break;
  583.         case CONTOUR_SRF:  fprintf(fp, " surface\n"); break;
  584.         case CONTOUR_BOTH: fprintf(fp, " both\n"); break;
  585.     }
  586.      fprintf(fp,"set %sclabel\n",(label_contours) ? "" : "no");
  587.     fprintf(fp,"set %shidden3d\n",(hidden3d) ? "" : "no");
  588.     fprintf(fp,"set cntrparam order %d\n", contour_order);
  589.     fprintf(fp,"set cntrparam ");
  590.     switch (contour_kind) {
  591.         case CONTOUR_KIND_LINEAR:    fprintf(fp, "linear\n"); break;
  592.         case CONTOUR_KIND_CUBIC_SPL: fprintf(fp, "cubicspline\n"); break;
  593.         case CONTOUR_KIND_BSPLINE:   fprintf(fp, "bspline\n"); break;
  594.     }
  595.     fprintf(fp,"set cntrparam levels ");
  596.     switch (levels_kind) {
  597.         int i;
  598.         case LEVELS_AUTO:
  599.             fprintf(fp, "auto %d\n", contour_levels);
  600.             break;
  601.         case LEVELS_INCREMENTAL:
  602.             fprintf(fp, "incremental %g,%g,%g\n",
  603.                 levels_list[0], levels_list[1], 
  604.                 levels_list[0]+levels_list[1]*contour_levels);
  605.             break;
  606.         case LEVELS_DISCRETE:
  607.             fprintf(fp, "discrete ");
  608.                 fprintf(fp, "%g", levels_list[0]);
  609.             for(i = 1; i < contour_levels; i++)
  610.                 fprintf(fp, ",%g ", levels_list[i]);
  611.             fprintf(fp, "\n");
  612.     }
  613.     fprintf(fp,"set cntrparam points %d\n", contour_pts);
  614.     fprintf(fp,"set size %g,%g\n",xsize,ysize);
  615.     fprintf(fp,"set data style ");
  616.     switch (data_style) {
  617.         case LINES: fprintf(fp,"lines\n"); break;
  618.         case POINTSTYLE: fprintf(fp,"points\n"); break;
  619.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  620.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  621.         case DOTS: fprintf(fp,"dots\n"); break;
  622.         case ERRORBARS: fprintf(fp,"errorbars\n"); break;
  623.         case BOXES: fprintf(fp,"boxes\n"); break;
  624.         case BOXERROR: fprintf(fp,"boxerrorbars\n"); break;
  625.         case STEPS: fprintf(fp,"steps\n"); break;       /* JG */
  626.     }
  627.     fprintf(fp,"set function style ");
  628.     switch (func_style) {
  629.         case LINES: fprintf(fp,"lines\n"); break;
  630.         case POINTSTYLE: fprintf(fp,"points\n"); break;
  631.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  632.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  633.         case DOTS: fprintf(fp,"dots\n"); break;
  634.         case ERRORBARS: fprintf(fp,"errorbars\n"); break;
  635.         case BOXES: fprintf(fp,"boxes\n"); break;
  636.         case BOXERROR: fprintf(fp,"boxerrorbars\n"); break;
  637.         case STEPS: fprintf(fp,"steps\n"); break;       /* JG */
  638.     }
  639.         fprintf(fp,"set %sxzeroaxis\n", (xzeroaxis)? "" : "no");
  640.         fprintf(fp,"set %syzeroaxis\n", (yzeroaxis)? "" : "no");
  641.         fprintf(fp,"set tics %s\n", (tic_in)? "in" : "out");
  642.         fprintf(fp,"set ticslevel %g\n", ticslevel);
  643.         save_tics(fp, xtics, 'x', &xticdef);
  644.         save_tics(fp, ytics, 'y', &yticdef);
  645.         save_tics(fp, ztics, 'z', &zticdef);
  646.         for (quote = &(title[0]); quote && *quote && (*quote != '"'); quote++)
  647.             ;
  648.         fprintf(fp,"set title %c%s%c %d,%d\n",*quote ? '\'' : '"',title,*quote ? '\'' : '"',title_xoffset,title_yoffset);
  649.     
  650.         if (timedate)
  651.         fprintf(fp,"set time %d,%d\n",time_xoffset,time_yoffset);
  652.     else
  653.         fprintf(fp,"set notime\n");
  654.      fprintf(fp,"set rrange [%g : %g]\n",rmin,rmax);
  655.     fprintf(fp,"set trange [%g : %g]\n",tmin,tmax);
  656.     fprintf(fp,"set urange [%g : %g]\n",umin,umax);
  657.     fprintf(fp,"set vrange [%g : %g]\n",vmin,vmax);
  658.         for (quote = &(xlabel[0]); quote && *quote && (*quote != '"'); quote++)
  659.             ;
  660.         fprintf(fp,"set xlabel %c%s%c %d,%d\n",*quote ? '\'' : '"',xlabel,*quote ? '\'' : '"',xlabel_xoffset,xlabel_yoffset);
  661.         fprintf(fp,"set xrange [%g : %g]\n",xmin,xmax);
  662.         for (quote = &(ylabel[0]); quote && *quote && (*quote != '"'); quote++)
  663.             ;
  664.         fprintf(fp,"set ylabel %c%s%c %d,%d\n",*quote ? '\'' : '"',ylabel,*quote ? '\'' : '"',ylabel_xoffset,ylabel_yoffset);
  665.         fprintf(fp,"set yrange [%g : %g]\n",ymin,ymax);
  666.         for (quote = &(zlabel[0]); quote && *quote && (*quote != '"'); quote++)
  667.             ;
  668.         fprintf(fp,"set zlabel %c%s%c %d,%d\n",*quote ? '\'' : '"',zlabel,*quote ? '\'' : '"',zlabel_xoffset,zlabel_yoffset);
  669.     fprintf(fp,"set zrange [%g : %g]\n",zmin,zmax);
  670.     fprintf(fp,"set %s %c\n", 
  671.         autoscale_r ? "autoscale" : "noautoscale", 'r');
  672.     fprintf(fp,"set %s %c\n", 
  673.         autoscale_t ? "autoscale" : "noautoscale", 't');
  674.     fprintf(fp,"set %s %c%c\n", 
  675.         (autoscale_y||autoscale_x) ? "autoscale" : "noautoscale", 
  676.         autoscale_x ? 'x' : ' ', autoscale_y ? 'y' : ' ');
  677.     fprintf(fp,"set %s %c\n", 
  678.         autoscale_z ? "autoscale" : "noautoscale", 'z');
  679.     fprintf(fp,"set zero %g\n",zero);
  680. }
  681.  
  682. save_tics(fp, onoff, axis, tdef)
  683.     FILE *fp;
  684.     TBOOLEAN onoff;
  685.     char axis;
  686.     struct ticdef *tdef;
  687. {
  688.     if (onoff) {
  689.        fprintf(fp,"set %ctics", axis);
  690.        switch(tdef->type) {
  691.           case TIC_COMPUTED: {
  692.              break;
  693.           }
  694.           case TIC_MONTH:{
  695.               fprintf(fp,"\nset %cmtics",axis);
  696.             break;
  697.           }
  698.             case TIC_DAY:{
  699.             fprintf(fp,"\nset %cdtics",axis);
  700.             break;
  701.             }
  702.           case TIC_SERIES: {
  703.                  if (tdef->def.series.end >= VERYLARGE)
  704.                  fprintf(fp, " %g,%g", tdef->def.series.start,
  705.                                         tdef->def.series.incr);
  706.                          else
  707.                  fprintf(fp, " %g,%g,%g", tdef->def.series.start,
  708.                                         tdef->def.series.incr, tdef->def.series.end);
  709.              break;
  710.           }
  711.           case TIC_USER: {
  712.              register struct ticmark *t;
  713.              fprintf(fp, " (");
  714.              for (t = tdef->def.user; t != NULL; t=t->next) {
  715.                 if (t->label)
  716.                   fprintf(fp, "\"%s\" ", t->label);
  717.                 if (t->next)
  718.                   fprintf(fp, "%g, ", t->position);
  719.                 else
  720.                   fprintf(fp, "%g", t->position);
  721.              }
  722.              fprintf(fp, ")");
  723.              break;
  724.           } 
  725.        }
  726.        fprintf(fp, "\n");
  727.     } else {
  728.        fprintf(fp,"set no%ctics\n", axis);
  729.     }
  730. }
  731.  
  732. load_file(fp, name)
  733.     FILE *fp;
  734.     char *name;
  735. {
  736.     register int len;
  737.     extern char input_line[];
  738.  
  739.     int start, left;
  740.     int more;
  741.     int stop = FALSE;
  742.  
  743.     lf_push(fp);            /* save state for errors and recursion */
  744.  
  745.     if (fp == (FILE *)NULL) {
  746.        char errbuf[BUFSIZ];
  747.        (void) sprintf(errbuf, "Cannot open load file '%s'", name);
  748.        os_error(errbuf, c_token);
  749.     } else {
  750.        /* go into non-interactive mode during load */
  751.        /* will be undone below, or in load_file_error */
  752.        interactive = FALSE;
  753.        inline_num = 0;
  754.        infile_name = name;
  755.  
  756.        while (!stop) {        /* read all commands in file */
  757.           /* read one command */
  758.           left = MAX_LINE_LEN;
  759.           start = 0;
  760.           more = TRUE;
  761.  
  762.           while (more) {
  763.              if (fgets(&(input_line[start]), left, fp) == (char *)NULL) {
  764.                 stop = TRUE; /* EOF in file */
  765.                 input_line[start] = '\0';
  766.                 more = FALSE;    
  767.              } else {
  768.                 inline_num++;
  769.                 len = strlen(input_line) - 1;
  770.                 if (input_line[len] == '\n') { /* remove any newline */
  771.                     input_line[len] = '\0';
  772.                     /* Look, len was 1-1 = 0 before, take care here! */
  773.                     if (len > 0) --len;
  774.                 } else if (len+1 >= left)
  775.                   int_error("Input line too long",NO_CARET);
  776.                  
  777.                 if (input_line[len] == '\\') { /* line continuation */
  778.                     start = len;
  779.                     left  = MAX_LINE_LEN - start; /* left -=len;*/
  780.                 } else
  781.                   more = FALSE;
  782.              }
  783.           }
  784.  
  785.           if (strlen(input_line) > 0) {
  786.              screen_ok = FALSE;    /* make sure command line is
  787.                                echoed on error */
  788.              do_line();
  789.           }
  790.        }
  791.     }
  792.  
  793.     /* pop state */
  794.     (void) lf_pop();        /* also closes file fp */
  795. }
  796.  
  797. /* pop from load_file state stack */
  798. static TBOOLEAN                /* FALSE if stack was empty */
  799. lf_pop()                    /* called by load_file and load_file_error */
  800. {
  801.     LFS *lf;
  802.  
  803.     if (lf_head == NULL)
  804.      return(FALSE);
  805.     else {
  806.        lf = lf_head;
  807.        if (lf->fp != (FILE *)NULL)
  808.         (void) fclose(lf->fp);
  809.        interactive = lf->interactive;
  810.        inline_num = lf->inline_num;
  811.        infile_name = lf->name;
  812.        lf_head = lf->prev;
  813.        free((char *)lf);
  814.        return(TRUE);
  815.     }
  816. }
  817.  
  818. /* push onto load_file state stack */
  819. /* essentially, we save information needed to undo the load_file changes */
  820. static void
  821. lf_push(fp)            /* called by load_file */
  822.     FILE *fp;
  823. {
  824.     LFS *lf;
  825.     
  826.     lf = (LFS *)alloc((unsigned long)sizeof(LFS), (char *)NULL);
  827.     if (lf == (LFS *)NULL) {
  828.        if (fp != (FILE *)NULL)
  829.         (void) fclose(fp);        /* it won't be otherwise */
  830.        int_error("not enough memory to load file", c_token);
  831.     }
  832.      
  833.     lf->fp = fp;            /* save this file pointer */
  834.     lf->name = infile_name;    /* save current name */
  835.     lf->interactive = interactive;    /* save current state */
  836.     lf->inline_num = inline_num; /* save current line number */
  837.     lf->prev = lf_head;        /* link to stack */
  838.     lf_head = lf;
  839. }
  840.  
  841. FILE *lf_top()        /* used for reread  vsnyder@math.jpl.nasa.gov */
  842. {   if (lf_head == (LFS *) NULL) return((FILE *)NULL);
  843.     return(lf_head->fp);
  844. }
  845.  
  846.  
  847. load_file_error()            /* called from main */
  848. {
  849.     /* clean up from error in load_file */
  850.     /* pop off everything on stack */
  851.     while(lf_pop())
  852.      ;
  853. }
  854.  
  855. /* find char c in string str; return p such that str[p]==c;
  856.  * if c not in str then p=strlen(str)
  857.  */
  858. int
  859. instring(str, c)
  860.     char *str;
  861.     char c;
  862. {
  863.     int pos = 0;
  864.  
  865.     while (str != NULL && *str != '\0' && c != *str) {
  866.        str++; 
  867.        pos++;
  868.     }
  869.     return (pos);
  870. }
  871.  
  872. show_functions()
  873. {
  874. register struct udft_entry *udf = first_udf;
  875.  
  876.     fprintf(stderr,"\n\tUser-Defined Functions:\n");
  877.  
  878.     while (udf) {
  879.         if (udf->definition)
  880.             fprintf(stderr,"\t%s\n",udf->definition);
  881.         else
  882.             fprintf(stderr,"\t%s is undefined\n",udf->udf_name);
  883.         udf = udf->next_udf;
  884.     }
  885. }
  886.  
  887.  
  888. show_at()
  889. {
  890.     (void) putc('\n',stderr);
  891.     disp_at(temp_at(),0);
  892. }
  893.  
  894.  
  895. disp_at(curr_at, level)
  896. struct at_type *curr_at;
  897. int level;
  898. {
  899. register int i, j;
  900. register union argument *arg;
  901.  
  902.     for (i = 0; i < curr_at->a_count; i++) {
  903.         (void) putc('\t',stderr);
  904.         for (j = 0; j < level; j++)
  905.             (void) putc(' ',stderr);    /* indent */
  906.  
  907.             /* print name of instruction */
  908.  
  909.         fputs(ft[(int)(curr_at->actions[i].index)].f_name,stderr);
  910.         arg = &(curr_at->actions[i].arg);
  911.  
  912.             /* now print optional argument */
  913.  
  914.         switch(curr_at->actions[i].index) {
  915.           case PUSH:    fprintf(stderr," %s\n", arg->udv_arg->udv_name);
  916.                     break;
  917.           case PUSHC:    (void) putc(' ',stderr);
  918.                     disp_value(stderr,&(arg->v_arg));
  919.                     (void) putc('\n',stderr);
  920.                     break;
  921.           case PUSHD1:    fprintf(stderr," %c dummy\n",
  922.                       arg->udf_arg->udf_name[0]);
  923.                     break;
  924.           case PUSHD2:    fprintf(stderr," %c dummy\n",
  925.                       arg->udf_arg->udf_name[1]);
  926.                     break;
  927.           case CALL:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  928.                     if(level < 6) {
  929.                     if (arg->udf_arg->at) {
  930.                         (void) putc('\n',stderr);
  931.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  932.                     } else
  933.                         fputs(" (undefined)\n",stderr);
  934.                     } else
  935.                         (void) putc('\n',stderr);
  936.                     break;
  937.           case CALLN:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  938.                     if(level < 6) {
  939.                     if (arg->udf_arg->at) {
  940.                         (void) putc('\n',stderr);
  941.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  942.                     } else
  943.                         fputs(" (undefined)\n",stderr);
  944.                     } else
  945.                         (void) putc('\n',stderr);
  946.                     break;
  947.           case JUMP:
  948.           case JUMPZ:
  949.           case JUMPNZ:
  950.           case JTERN:
  951.                     fprintf(stderr," +%d\n",arg->j_arg);
  952.                     break;
  953.           default:
  954.                     (void) putc('\n',stderr);
  955.         }
  956.     }
  957. }
  958.